package whf.framework.workflow.client;

import java.util.ArrayList;
import java.util.List;

import org.jbpm.graph.def.Node;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.def.Transition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;

/**
 * @author king
 * @modify May 13, 2008 10:14:26 AM
 * 
 */
@SuppressWarnings(value="unchecked")
public class WebflowXmlBuilder {
	public static String buildXml(ProcessInstance processInstance) {
		ProcessDefinition processDefinition = processInstance.getProcessDefinition();
		
		Element WebFlow = new Element("WebFlow");

		Element FlowConfig = new Element("FlowConfig");
		
		if(processDefinition != null){
			Element BaseProperties = new Element("BaseProperties");
			BaseProperties.setAttribute("flowId", String.valueOf(processDefinition.getId()));
			BaseProperties.setAttribute("flowText", processDefinition.getName());
			FlowConfig.addContent(BaseProperties);
			
			Element VMLProperties = new Element("VMLProperties");
			VMLProperties.setAttribute("stepTextColor", "blue");
			VMLProperties.setAttribute("stepStrokeColor", "blue");
			VMLProperties.setAttribute("stepShadowColor", "#b3b3b3");
			VMLProperties.setAttribute("stepFocusedStrokeColor", "red");
			VMLProperties.setAttribute("isStepShadow", "T");
			VMLProperties.setAttribute("actionStrokeColor", "blue");
			VMLProperties.setAttribute("actionTextColor", "");
			VMLProperties.setAttribute("actionFocusedStrokeColor", "red");
			VMLProperties.setAttribute("sStepTextColor", "red");
			VMLProperties.setAttribute("sStepStrokeColor", "red");
			VMLProperties.setAttribute("stepColor1", "blue");
			VMLProperties.setAttribute("stepColor2", "white");
			VMLProperties.setAttribute("isStep3D", "true");
			VMLProperties.setAttribute("step3DDepth", "5");
			FlowConfig.addContent(VMLProperties);
			
			Element FlowProperties = new Element("FlowProperties");
			FlowProperties.setAttribute("flowMode", "");
			FlowProperties.setAttribute("startTime", "");
			FlowProperties.setAttribute("endTime", "");
			FlowProperties.setAttribute("ifMonitor", "");
			FlowProperties.setAttribute("runMode", "");
			FlowProperties.setAttribute("noteMode", "");
			FlowProperties.setAttribute("activeForm", "true");
			FlowProperties.setAttribute("autoExe", "true");
			FlowConfig.addContent(FlowProperties);
		}
		WebFlow.addContent(FlowConfig);
		//
		
		List<Node> nodes = new ArrayList<Node>();
		List<Transition> transitions = new ArrayList<Transition>();
		addNodesAndTransitionToCollection(processDefinition.getStartState(), nodes, transitions);
		
		Element Steps = new Element("Steps");
		for(int i=0; i< nodes.size(); i++){
			Node node = nodes.get(i);
			Element Step = new Element("Step");
			Element BaseProperties = new Element("BaseProperties");
			BaseProperties.setAttribute("id", String.valueOf(node.getId()));
			BaseProperties.setAttribute("text", node.getName());
			if(i == 0){
				BaseProperties.setAttribute("stepType", "BeginStep");
			} else if(node.hasNoLeavingTransitions()){
				BaseProperties.setAttribute("stepType", "EndStep");
			} else {
				BaseProperties.setAttribute("stepType", "NormalStep");
			}
			Step.addContent(BaseProperties);
			
			Element VMLProperties = new Element("VMLProperties");
			VMLProperties.setAttribute("width", "170");
			VMLProperties.setAttribute("height", "180");
			
			VMLProperties.setAttribute("x", String.valueOf(i * 280));
			VMLProperties.setAttribute("y", String.valueOf(50));
			
			VMLProperties.setAttribute("textWeight", "");
			if(processInstance.getRootToken().getNode().getId() == node.getId()){
				VMLProperties.setAttribute("strokeWeight", "3");
			} else {
				VMLProperties.setAttribute("strokeWeight", "");
			}
			VMLProperties.setAttribute("isFocused", "");
			VMLProperties.setAttribute("zIndex", "");
			Step.addContent(VMLProperties);
			
			Element FlowProperties = new Element("FlowProperties");
			Step.addContent(FlowProperties);
			
			Steps.addContent(Step);
		}
		WebFlow.addContent(Steps);
		//
		Element Actions = new Element("Actions");
		for(int i=0; i< transitions.size(); i++){
			Transition transition = transitions.get(i);
			Element Action  = new Element("Action");
			
			Element BaseProperties = new Element("BaseProperties");
			BaseProperties.setAttribute("id", String.valueOf(transition.getId()));
			BaseProperties.setAttribute("text", transition.getName());
			BaseProperties.setAttribute("actionType", "PolyLine");
			BaseProperties.setAttribute("from", transition.getFrom() == null?"":String.valueOf(transition.getFrom().getId()));
			BaseProperties.setAttribute("to", transition.getTo() == null?"":String.valueOf(transition.getTo().getId()));
			Action.addContent(BaseProperties);
			
			Element VMLProperties = new Element("VMLProperties");
			VMLProperties.setAttribute("startArrow", "");
			VMLProperties.setAttribute("endArrow", "classic");
			VMLProperties.setAttribute("strokeWeight", "");
			VMLProperties.setAttribute("isFocused", "");
			VMLProperties.setAttribute("zIndex", "");
			Action.addContent(VMLProperties);
			
			Element FlowProperties = new Element("FlowProperties");
			Action.addContent(FlowProperties);
			
			Actions.addContent(Action);
		}
		WebFlow.addContent(Actions);
		//

		Document doc = new Document(WebFlow);
		XMLOutputter xmlOutputter = new XMLOutputter();
		return xmlOutputter.outputString(doc);
	}
	
	public static void addNodesAndTransitionToCollection(Node node, List<Node> nodes, List<Transition> transitions) {
		if(nodes.contains(node)) {
			nodes.add(node);
		}
		List<Transition> leavingTransitions = node.getLeavingTransitions();
		for(Transition t: leavingTransitions) {
			if(transitions.contains(t)) {
				continue;
			} else {
				transitions.add(t);
				addNodesAndTransitionToCollection(t.getTo(), nodes, transitions);
			}
		}
	}
	
	static class FlowNode {
		
	}
}